package com.ds.infra.rpc.autoconfigure;

import com.ds.infra.rpc.autoconfigure.condition.OnRpcConsumer;
import com.ds.infra.rpc.autoconfigure.scanner.RpcReferenceScanner;
import com.ds.infra.rpc.core.loadbalance.LoadBalance;
import com.ds.infra.rpc.core.loadbalance.RoundRobinLoadBalance;
import com.ds.infra.rpc.core.transport.client.NettyClient;
import com.ds.infra.rpc.properties.RpcConsumerProperties;
import com.ds.infra.rpc.properties.RpcProperties;
import com.ds.infra.rpc.registry.service.ServiceDiscovery;
import com.ds.infra.rpc.registry.service.impl.ZkServiceDiscovery;
import com.ds.infra.rpc.registry.util.ServiceKeyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;
import java.util.Map;

/**
 * 作用：RPC消费者自动配置类
 *
 * @author WeiShaoying
 */
@Configuration
@OnRpcConsumer
@EnableConfigurationProperties(RpcConsumerProperties.class)
@Slf4j
public class RpcConsumerAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public RpcReferenceScanner rpcReferenceScanner() {
        log.info("====> RpcReferenceScanner init");
        return new RpcReferenceScanner();
    }

    @Bean
    @ConditionalOnMissingBean
    public ServiceDiscovery serviceDiscovery(RpcProperties properties) {
        log.info("====> ZkServiceDiscovery init");
        return new ZkServiceDiscovery(properties.getZkAddress());
    }

    // @Bean
    @ConditionalOnMissingBean
    public NettyClient nettyClient(RpcProperties properties) {
        log.info("====> NettyClient init 00");
        // 实际使用时应从服务发现获取地址
        // NettyClient client = new NettyClient("localhost", properties.getServerPort());
        NettyClient client = new NettyClient("192.168.0.108", properties.getServerPort());
        log.info("====> NettyClient connected to server: {}:{}", "localhost", properties.getServerPort());
        client.connect(); // 建立连接
        return client;
    }

    @Bean("roundRobinLoadBalance")
    @ConditionalOnMissingBean
    public LoadBalance loadBalance() {
        // 默认使用轮询负载均衡
        return new RoundRobinLoadBalance();
        // 根据配置决定使用哪种策略
        // return properties.getLoadBalanceStrategy().equals("roundRobin")
        //     ? new RoundRobinLoadBalance()
        //     : new RandomLoadBalance();
    }


    @Bean
    @ConditionalOnMissingBean
    public NettyClient nettyClient2(ServiceDiscovery serviceDiscovery, RpcConsumerProperties properties, LoadBalance loadBalance) {
        log.info("====> NettyClient init");
        // 1. 从服务发现获取目标服务地址（动态获取）
        List<Map<String, Object>> instances;
        try {
            String serviceKey = ServiceKeyUtils.buildServiceKey(properties.getServiceName(), properties.getVersion());
            instances = serviceDiscovery.discover(serviceKey);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (instances.isEmpty()) {
            throw new IllegalStateException("No available service instances");
        }

        // 2. 负载均衡选择实例
        Map<String, Object> instance = loadBalance.select(instances);
        String[] hostPort = ((String) instance.get("serviceAddress")).split(":");
        log.info("====> NettyClient connected to server: {}:{}", hostPort[0], hostPort[1]);
        // 3. 创建客户端连接
        NettyClient client = new NettyClient(hostPort[0], Integer.parseInt(hostPort[1]));
        client.connect();
        return client;
    }


    // @Bean
    // @ConditionalOnMissingBean
    // public NettyClient nettyClient(ServiceDiscovery serviceDiscovery,
    //                                RpcConfig config,
    //                                LoadBalance loadBalance,
    //                                ObjectProvider<List<RpcReferencePostProcessor>> postProcessors) {
    //     return new ServiceDiscoveryClient(serviceDiscovery, config, loadBalance, postProcessors);
    // }

    /**
     * 支持动态服务发现的客户端包装类
     */
    // @RequiredArgsConstructor
    // public static class ServiceDiscoveryClient implements RpcClient {
    //     private final ServiceDiscovery discovery;
    //     private final RpcConfig config;
    //     private final LoadBalance loadBalance;
    //     private final List<RpcReferencePostProcessor> postProcessors;
    //     private volatile NettyClient delegate;
    //
    //     @PostConstruct
    //     public void init() {
    //         refreshClient();
    //         discovery.watchService(null, this::refreshClient); // 监听所有服务变化
    //     }
    //
    //     private void refreshClient() {
    //         // 1. 获取所有服务（实际使用时按需过滤）
    //         Map<String, List<Map<String, Object>>> services = discovery.getAllServices();
    //         if (services.isEmpty()) {
    //             throw new IllegalStateException("No available services");
    //         }
    //
    //         // 2. 选择目标服务（可通过后处理器动态修改）
    //         String targetService = postProcessors.stream()
    //                 .map(p -> p.getTargetService())
    //                 .filter(Objects::nonNull)
    //                 .findFirst()
    //                 .orElseGet(() -> services.keySet().iterator().next());
    //
    //         // 3. 负载均衡选择实例
    //         Map<String, Object> instance = loadBalance.select(services.get(targetService));
    //         String[] hostPort = ((String) instance.get("address")).split(":");
    //
    //         // 4. 重建客户端
    //         if (delegate != null) delegate.shutdown();
    //         this.delegate = new NettyClient(hostPort[0], Integer.parseInt(hostPort[1]), config);
    //     }
    //
    //     @Override
    //     public CompletableFuture<RpcResponse> send(RpcProtocol<RpcRequest> protocol) {
    //         return delegate.send(protocol);
    //     }
    //
    //     @Override
    //     public void shutdown() {
    //         delegate.shutdown();
    //     }
    // }
}
